package org.admin.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import core.data.DataHandle;
import org.admin.entity.domain.Menu;
import org.admin.entity.domain.Perms;
import org.admin.entity.domain.PermsGroup;
import org.admin.entity.domain.RolePermsGroup;
import org.admin.entity.dto.PermsGroupDto;
import org.admin.entity.vo.PermsGroupFetchVo;
import org.admin.mapper.PermsGroupMapper;
import org.admin.mapper.RolePermsGroupMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class PermsGroupService {
    @Autowired
    private PermsGroupMapper mapper;
    @Autowired
    private RolePermsGroupMapper rolePermsGroupMapper;
    public void query(DataHandle<PermsGroupDto, IPage<PermsGroupFetchVo>> handle) {
        PermsGroupDto params = handle.getParams();
        MPJLambdaWrapper<PermsGroup> query = new MPJLambdaWrapper<>();
        // QueryWrapper<PermsGroup> query = new QueryWrapper<>();
        query.selectAll(PermsGroup.class)
                .selectFunc(() -> "COUNT(%s)", Perms::getId, PermsGroupFetchVo::getPermsCount)
                .leftJoin(Perms.class,  Perms::getGroupId, PermsGroup::getId)
                .orderByDesc(PermsGroup::getCreatedAt)
                .groupBy(PermsGroup::getId);
        if(params.getName() != null){
            query.like(PermsGroup::getName, "%" + params.getName() + "%");
        }


        IPage<PermsGroupFetchVo> pageApp = mapper.selectJoinPage(
                new Page<>(params.getCurrent(), params.getSize()),
                PermsGroupFetchVo.class,
                 query);
        handle.success(pageApp);
    }

    public void fetch(DataHandle<PermsGroupDto, PermsGroupFetchVo> handle) {
        PermsGroupDto params = handle.getParams();
        PermsGroup group = mapper.selectById(params.getId());
        if(group == null){
            handle.failure("id", "权限分组ID不存在或已删除");
            return;
        }
        handle.success(new PermsGroupFetchVo(group));
    }

    public void create(DataHandle<PermsGroupDto, ?> handle) {
        PermsGroupDto params = handle.getParams();
        PermsGroup group = null;
        Date now = new Date();
        boolean doUpdate = false;
        QueryWrapper<PermsGroup> query = new QueryWrapper<>();
        if(params.getId() != null){
            group = mapper.selectById(params.getId());
            if(group == null){
                handle.failure("id", "权限组ID无效");
                return;
            }
            query.ne("id", params.getId());
            doUpdate = true;
        }else{
            group = new PermsGroup();
            group.setCreatedAt(now);
        }
        // 重复检测
        query.eq("name", params.getName());
        if(mapper.selectCount(query) > 0) {
            handle.failure("name",  "分组名称已存在");
            return;
        }
        // 创建更新
        group.setName(params.getName());
        group.setDetail(params.getDetail());
        group.setUpdatedAt(now);

        if(doUpdate){
            mapper.updateById(group);
        }else{
            mapper.insert(group);
        }
        handle.success();
    }

    public void remove(DataHandle<PermsGroupDto, ?> handle) {
        PermsGroupDto params = handle.getParams();
        List<Integer> ids = params.getIds();
        if(ids.isEmpty()){
            handle.failure("ids", "未提供删除项");
            return;
        }
        // 查表校验 ids 中每项的有效性
        // 关联查询 力度表
        // 关联查询 菜单表
        Set<Integer> idSet = new HashSet<>(ids);
        List<Map<String, Object>> list = JoinWrappers.lambda(PermsGroup.class)
                .select(PermsGroup::getId, PermsGroup::getName)
                .selectFunc(() -> "COUNT(%s)", Perms::getId, "permsCount")
                .selectFunc(() -> "COUNT(%s)", Menu::getId, "menuCount")
                .leftJoin(Perms.class, Perms::getGroupId, PermsGroup::getId)
                .leftJoin(Menu.class, Menu::getGroupId, PermsGroup::getId)
                .in(PermsGroup::getId, ids)
                .list(HashMap.class)
                .stream()
                .map(item -> (Map<String, Object>) new HashMap<String, Object>() {{
                    put("id", item.get("id"));
                    put("name", item.get("name"));
                    put("permsCount", item.get("permsCount"));
                    put("menuCount", item.get("menuCount"));
                }})
                .toList();

        for(Map<String, Object> item : list){
            if(item.get("menuCount") != null && (long) item.get("permsCount") > 0){
                handle.failure(item.get("name") + ": 存在子项，请删除后再试");
                return;
            }else if(item.get("menuCount") != null && (long) item.get("menuCount") > 0){
                handle.failure(item.get("name") + ": 存在菜单，请删除后再试");
                return;
            }else{
                idSet.remove((int) item.get("id"));
            }
        }

        if(!idSet.isEmpty()){
            String strIds = idSet.stream().map(Object::toString)
                    .collect(Collectors.joining(", "));
            handle.failure("ids", "提供项[" + strIds + "]不存在或已删除");
            return;
        }

        mapper.deleteBatchIds(ids);
        // 关联删除角色力度组表
        rolePermsGroupMapper.delete(JoinWrappers.delete(RolePermsGroup.class).in(RolePermsGroup::getGroupId, ids));
        handle.success();
    }
}
